/**
 * 火山引擎语音合成服务
 * 封装了TTS API请求、参数构建、缓存管理和错误处理
 */
export default class TTSService {
  constructor(options = {}) {
    // 初始化配置
    this.appid = options.appid;
    this.token = options.token;
    this.voiceType = options.voiceType || 'zh_male_M392_conversation_wvae_bigtts'; // 默认音色
    this.cluster = options.cluster || 'volcano_tts'; // 默认集群
    this.apiUrl = 'https://openspeech.bytedance.com/api/v1/tts';
    
    // 音频播放器
    this.audioContext = null;
    
    // 音频缓存
    this.audioCache = {};
    
    // 初始化音频播放器
    this.initAudioContext();
  }
  
  /**
   * 初始化音频播放器
   */
  initAudioContext() {
    if (!this.audioContext) {
      this.audioContext = uni.createInnerAudioContext();
      
      // 监听播放事件
      this.audioContext.onPlay(() => {
        console.log('[TTSService] 开始播放');
        if (this.onPlayStart) this.onPlayStart();
      });
      
      // 监听播放结束
      this.audioContext.onEnded(() => {
        console.log('[TTSService] 播放结束');
        if (this.onPlayEnd) this.onPlayEnd();
      });
      
      // 监听播放错误
      this.audioContext.onError((res) => {
        console.error('[TTSService] 播放错误:', res.errMsg);
        if (this.onPlayError) this.onPlayError(res);
      });
      
      // 监听播放停止
      this.audioContext.onStop(() => {
        console.log('[TTSService] 播放停止');
        if (this.onPlayStop) this.onPlayStop();
      });
    }
  }
  
  /**
   * 生成UUID，用于请求追溯
   */
  generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      const r = Math.random() * 16 | 0;
      const v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }
  
  /**
   * 设置播放事件回调
   * @param {Object} callbacks - 包含各种播放事件回调的对象
   */
  setPlayCallbacks(callbacks = {}) {
    this.onPlayStart = callbacks.onStart;
    this.onPlayEnd = callbacks.onEnd;
    this.onPlayStop = callbacks.onStop;
    this.onPlayError = callbacks.onError;
  }
  
  /**
   * 合成语音
   * @param {string} text - 要合成的文本
   * @param {string} messageId - 消息ID，用于缓存
   * @param {boolean} silent - 是否静默模式（不显示加载提示）
   * @returns {Promise<string>} - 返回base64编码的音频数据
   */
  synthesize(text, messageId, silent = false) {
    return new Promise((resolve, reject) => {
      // 检查缓存
      if (messageId && this.audioCache[messageId]) {
        console.log('[TTSService] 使用缓存的语音数据');
        resolve(this.audioCache[messageId]);
        return;
      }
      
      if (!silent) {
        uni.showLoading({ title: '语音合成中...' });
      }
      
      // 构建请求参数
      const requestPayload = {
        app: {
          appid: this.appid,
          token: this.token,
          cluster: this.cluster
        },
        user: {
          uid: messageId || this.generateUUID().substring(0, 8)
        },
        audio: {
          voice_type: this.voiceType,
          encoding: 'mp3',
          speed_ratio: 1.0,
          rate: 24000
        },
        request: {
          reqid: this.generateUUID(),
          text: text,
          operation: 'query'
        }
      };
      
      // 发送API请求
      uni.request({
        url: this.apiUrl,
        method: 'POST',
        header: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer;${this.token}`
        },
        data: requestPayload,
        success: (res) => {
          if (!silent) {
            uni.hideLoading();
          }
          
          if (res.data && res.data.code === 3000 && res.data.data) {
            console.log('[TTSService] TTS API 调用成功');
            const base64Data = res.data.data;
            
            // 缓存语音数据
            if (messageId) {
              this.audioCache[messageId] = base64Data;
            }
            
            resolve(base64Data);
          } else {
            console.error('[TTSService] TTS API 返回错误:', res.data);
            const errorCode = res.data?.code || 'unknown';
            const errorMsg = res.data?.message || '未知错误';
            
            if (!silent) {
              uni.showToast({
                title: `合成失败: ${this.getErrorMessage(errorCode)}`,
                icon: 'none',
                duration: 3000
              });
            }
            
            reject({
              code: errorCode,
              message: errorMsg
            });
          }
        },
        fail: (err) => {
          if (!silent) {
            uni.hideLoading();
          }
          console.error('[TTSService] TTS API 请求失败:', err);
          
          if (!silent) {
            uni.showToast({
              title: '语音服务请求失败',
              icon: 'none'
            });
          }
          
          reject({
            code: 'REQUEST_FAIL',
            message: err.errMsg || '网络请求失败'
          });
        }
      });
    });
  }
  
  /**
   * 播放语音
   * @param {string} base64Data - base64编码的音频数据
   * @returns {Promise<void>}
   */
  play(base64Data) {
    return new Promise((resolve, reject) => {
      try {
        // 停止可能正在播放的音频
        if (this.audioContext.paused === false) {
          this.audioContext.stop();
        }
        
        // 设置音频源并播放
        this.audioContext.src = `data:audio/mp3;base64,${base64Data}`;
        this.audioContext.play();
        
        // 监听一次性播放结束事件
        const onEndedOnce = () => {
          this.audioContext.offEnded(onEndedOnce);
          resolve();
        };
        
        this.audioContext.onEnded(onEndedOnce);
      } catch (error) {
        console.error('[TTSService] 播放音频失败:', error);
        reject(error);
      }
    });
  }
  
  /**
   * 合成并播放
   * @param {string} text - 要合成的文本
   * @param {string} messageId - 消息ID，用于缓存
   * @param {boolean} silent - 是否静默模式（不显示加载提示）
   * @returns {Promise<void>}
   */
  async synthesizeAndPlay(text, messageId, silent = false) {
    try {
      const base64Data = await this.synthesize(text, messageId, silent);
      await this.play(base64Data);
      return true;
    } catch (error) {
      console.error('[TTSService] 合成并播放失败:', error);
      return false;
    }
  }
  
  /**
   * 从缓存播放
   * @param {string} messageId - 消息ID
   * @returns {Promise<boolean>} - 是否成功播放
   */
  async playFromCache(messageId) {
    if (!this.audioCache[messageId]) {
      console.log('[TTSService] 缓存中不存在此消息ID的语音');
      return false;
    }
    
    try {
      await this.play(this.audioCache[messageId]);
      return true;
    } catch (error) {
      console.error('[TTSService] 从缓存播放失败:', error);
      return false;
    }
  }
  
  /**
   * 停止播放
   */
  stop() {
    if (this.audioContext && this.audioContext.paused === false) {
      this.audioContext.stop();
    }
  }
  
  /**
   * 清除指定消息ID的缓存
   * @param {string} messageId - 消息ID
   */
  clearCache(messageId) {
    if (messageId && this.audioCache[messageId]) {
      delete this.audioCache[messageId];
    }
  }
  
  /**
   * 清除所有缓存
   */
  clearAllCache() {
    this.audioCache = {};
  }
  
  /**
   * 获取缓存大小
   * @returns {number} - 缓存中的条目数
   */
  getCacheSize() {
    return Object.keys(this.audioCache).length;
  }
  
  /**
   * 工具方法：根据错误码获取友好的错误提示
   * @param {number|string} errorCode - API返回的错误码
   * @returns {string} - 对应的错误提示文本
   */
  getErrorMessage(errorCode) {
    const errorMessages = {
      3001: '请求参数无效',
      3002: '无访问权限',
      3003: '访问超频',
      3005: '服务器繁忙，请稍后重试',
      3010: '文本过长',
      3022: '合成出错，请重试',
      'REQUEST_FAIL': '网络请求失败，请检查网络连接'
    };
    return errorMessages[errorCode] || '发生未知错误，请重试';
  }
}
